
package com.powerunion.datacollection.report.excelreport.base;

import java.util.ArrayList;
import java.util.List;

import com.powerunion.datacollection.report.excelreport.Logger;
import com.powerunion.datacollection.report.excelreport.base.element.Property;
import com.powerunion.datacollection.report.excelreport.base.element.Templet;
import com.powerunion.datacollection.report.excelreport.config.ReportConfig.SheetConfig;
import com.powerunion.datacollection.report.excelreport.util.AnalyseTempletTool;
import com.powerunion.datacollection.report.excelreport.util.HelpTools;

import jxl.Range;
import jxl.write.WritableImage;
import jxl.write.WritableSheet;

/**
 * 所有带的基类（组也是属于带的一种). 带表示报表中的一个可重复输出的区域，
 * 该区域根据带的不同类型会产生不同的输出效果，如band它所对应的body区是根据band对应的数据源的记录条数来进行输出的，
 * 在band中假设对应的数据源为5条记录那么该band对应的body区也会打印5次。
 * 
 * @author juny
 */
public abstract class BaseBand extends BaseElement implements ITempletContainer {
	private static Logger log = Logger.getLogger(BaseBand.class);
	/**
     * @param container 父容器对象。
     */
    public BaseBand(ITempletContainer container) {
        super(container);
    }
    
    public void iniElement() {
        if(null != headTemplet){
            ((BaseElement)headTemplet).iniElement();
        }
        
        if(null != detailTemplet){
            ((BaseElement)detailTemplet).iniElement();
        }
        
        if(null != bottomTemplet){
            ((BaseElement)bottomTemplet).iniElement();
        }
    }

    /**
     * 设置当前报表配置文件信息。这个函数以后可能会移掉，当前配置文件信息对象应该放在
     * 参数对象中去给当前所有对象共享才比较合理，而无需要每个对象都去显式的设置。
     * @param sheetConfig
     */
    public void setReportConfig(SheetConfig sheetConfig){
        this.sheetConfig = sheetConfig;
    }
    protected SheetConfig sheetConfig = null;
    
    /**
     * 取得当前band对象在报表写入数据的起始行
     */
    public int getRealBeginRow(){
        return realBeginRow;
    }
    protected int realBeginRow = 0;
    
    /**
     * 取得当前band对象总共写入了多少行数据
     */
    public int getRealRowCount(){
        return realRowCount;
    }
    protected int realRowCount = 0;

    /**
     * 设置头容器。
     */
    public void setHearder() {
        this.headTemplet = new Templet(this.getParentContainer()); 
        curTemplet = this.headTemplet;
    }

    /**
     * 设置明细容器
     * @param beginCol
     * @param beginRow
     */
    public void setDetail(int beginCol, int beginRow) {
        this.detailTemplet = new Templet(this.getParentContainer());
        this.detailTemplet.setBegin(beginCol, beginRow);
        this.curTemplet.setEnd(beginCol, beginRow);
        this.curTemplet = this.detailTemplet;
    }

    /**
     * 设置当前带的结束位置
     * @param beginCol
     * @param beginRow
     */
    public void setBottom(int beginCol, int beginRow) {
        this.bottomTemplet = new Templet(this.getParentContainer());
        this.bottomTemplet.setBegin(beginCol, beginRow);
        this.curTemplet.setEnd(beginCol, beginRow);
        this.curTemplet = this.bottomTemplet;
    }
    
    /* (non-Javadoc)
     * @see excel.report.util.ITempletContainer#setBegin(int, int)
     */
    public void setBegin(int beginCol, int beginRow) {
        curTemplet.setBegin(beginCol, beginRow);
    }

    /* (non-Javadoc)
     * @see excel.report.util.ITempletContainer#setEnd(int, int)
     */
    public void setEnd(int endCol, int endRow) {
        curTemplet.setEnd(endCol, endRow);
    }

    /**
     * 判断传入模板信息是否是当前容器对象的头。
     * @param templet	模板定义内容
     * @return true 当前传入模板是当前带对象的头 false 表示不是
     */
    public boolean isHead(String templet) {
        return isSameBand(templet);
    }

    /**
     * 判断传入模板信息是否是当前容器对象的body区。
     * @param templet	模板定义内容
     * @return true 当前传入模板是当前带对象的body区 false 表示不是
     */
    public boolean isDetail(String templet) {
        return isSameBand(templet);
    }

    /**
     * 判断传入模板信息是否是当前容器对象的foot区。
     * @param templet	模板定义内容
     * @return true 当前传入模板是当前带对象的foot区 false 表示不是
     */
    public boolean isBottom(String templet) {
        return isSameBand(templet);
    }

    /**
     * 判断传入模板信息是否是当前容器对象的结束位置。
     * @param templet	模板定义内容
     * @return true 当前传入模板是当前带对象的结束位置 false 表示不是
     */
    public boolean isEnd(String templet) {
        return isSameBand(templet);
    }
    
    private boolean isSameBand(String templet){
        String name = AnalyseTempletTool.getPorperty(
                templet, 
				AnalyseTempletTool.PROPERTY_NAME
        		);
        if(this.getName().equals(name)){
            return true;
        }
        return false;
    }
    
    /*
     * @see excel.report.util.ITempletContainer#getContainElements()
     */
    public List getContainElements() {
        return null;
    }

    /*
     * @see excel.report.util.ITempletContainer#getElement(java.lang.String)
     */
    public BaseElement getElement(String name) {
        BaseElement element = null;
        if(null != headTemplet){
	        element = headTemplet.getElement(name);
	        if(null != element){
	            return element;
	        }
        }
        
        if(null != detailTemplet){
	        element = this.detailTemplet.getElement(name);
	        if(null != element){
	            return element;
	        }
        }
        
        if(null != bottomTemplet){
	        element = this.bottomTemplet.getElement(name);
	        if(null != element){
	            return element;
	        }
        }
        return null;
    }

    /*
     * @see excel.report.util.ITempletContainer#addElement(excel.report.util.BaseElement)
     */
    public void addElement(BaseElement element, int col, int row) {
        this.curTemplet.addElement(element, col, row);
    }

    /*
     * @see excel.report.util.ITempletContainer#getElement(int, int)
     */
    public BaseElement getElement(int col, int row) {
        BaseElement element = null;
        if(null != headTemplet){
	        element = headTemplet.getElement(col, row);
	        if(null != element){
	            return element;
	        }
        }
        
        if(null != this.detailTemplet){
	        element = this.detailTemplet.getElement(col, row);
	        if(null != element){
	            return element;
	        }
        }
        
        if(null != this.bottomTemplet){
	        element = this.bottomTemplet.getElement(col, row);
	        if(null != element){
	            return element;
	        }
        }
        return null;
    }

    /*
     * @see excel.report.util.ITempletContainer#getBeginCol()
     */
    public int getBeginCol() {
        return null == headTemplet ? 0 : headTemplet.getBeginCol();
    }

    /*
     * @see excel.report.util.ITempletContainer#getBeginRow()
     */
    public int getBeginRow() {
        return null == headTemplet ? 0 : headTemplet.getBeginRow();
    }

    /*
     * @see excel.report.util.ITempletContainer#getEndCol()
     */
    public int getEndCol() {
        return null == bottomTemplet ? 0 : bottomTemplet.getEndCol();
    }

    /* 
     * @see excel.report.util.ITempletContainer#getEndRow()
     */
    public int getEndRow() {
        return null == bottomTemplet ? 0 : bottomTemplet.getEndRow();
    }
    
    /* (non-Javadoc)
     * 添加一个合并单元格信息到容器中。
     */
    public boolean addMergedCell(Range range) {
        if(null != headTemplet){
            if(headTemplet.addMergedCell(range)){
                return true;
            }
        }
        
        if(null != detailTemplet){
            if(detailTemplet.addMergedCell(range)){
                return true;
            }
        }
        
        if(null != bottomTemplet){
            if(bottomTemplet.addMergedCell(range)){
                return true;
            }
        }
        
        return false;
    }

    /* (non-Javadoc)
     * @see excel.report.util.ITempletContainer#getMergedCells()
     */
    public List getMergedCells() {
    	//还未实现
        return null;
    }
    
    /*
     * (non-Javadoc)
     * @see excel.report.base.ITempletContainer#getImages()
     */
    public List getImages() {
    	if(images != null){
    		return images;
    	}
    	
    	images = new ArrayList();
    	List tImages = null;
    	
    	if(null != headTemplet){
    		tImages = headTemplet.getImages();
            if(null != tImages){
            	images.addAll(tImages);
            	tImages = null;
            }
        }
        
        if(null != detailTemplet){
        	tImages = detailTemplet.getImages();
            if(null != tImages){
            	images.addAll(tImages);
            	tImages = null;
            }
        }
        
        if(null != bottomTemplet){
        	tImages = bottomTemplet.getImages();
            if(null != tImages){
            	images.addAll(tImages);
            	tImages = null;
            }
        }
        
        return images;
	}
    private List images = null;

	/*
     * (non-Javadoc)
     * @see excel.report.base.ITempletContainer#addImage(jxl.write.WritableImage)
     */
    public boolean addImage(WritableImage image) {
    	if(null != headTemplet){
            if(headTemplet.addImage(image)){
                return true;
            }
        }
        
        if(null != detailTemplet){
            if(detailTemplet.addImage(image)){
                return true;
            }
        }
        
        if(null != bottomTemplet){
            if(bottomTemplet.addImage(image)){
                return true;
            }
        }
        
        return false;
	}

    /*
     * (non-Javadoc)
     * @see excel.report.base.ITempletContainer#removeAllTempletImages(jxl.write.WritableSheet)
     */
	public boolean removeAllTempletImages(WritableSheet sheet) {
        if(null != headTemplet){
            headTemplet.removeAllTempletImages(sheet);
        }
        
        if(null != detailTemplet){
            detailTemplet.removeAllTempletImages(sheet);
        }
        
        if(null != bottomTemplet){
            bottomTemplet.removeAllTempletImages(sheet);
        }
        return true;
    }

	/**
	 * 生成当前带对象的头部区的报表数据
	 * @param param		参数对象
	 * @throws Exception
	 */
    protected void writeHead(Parameter param) throws Exception{
        if(null != this.headTemplet){
            this.headTemplet.write(param);
        }
    }
    
    /**
	 * 生成当前带对象的body区的报表数据
	 * @param param		参数对象
	 * @throws Exception
	 */
    protected void writeBody(Parameter param) throws Exception{
        if(null != this.detailTemplet){
            this.detailTemplet.write(param);
        }
    }
    
    /**
	 * 生成当前带对象的foot区的报表数据
	 * @param param		参数对象
	 * @throws Exception
	 */
    protected void writeFoot(Parameter param) throws Exception{
        if(null != this.bottomTemplet){
            this.bottomTemplet.write(param);
        }
    }
    
    /*
     * (non-Javadoc)
     * @see net.excel.report.base.BaseElement#getPropertyInstance()
     */
    protected Property getPropertyInstance(){
        return new BandProperty();
    }
    
    protected void mergeColumn(int beginRow, 
    						 int endRow, 
    						 Parameter param
    						 )throws Exception{
    	int[] cols = ((BandProperty)this.getProperty()).getMergeColum();
    	if(null == cols) return;
    	for(int i=0; i<cols.length; i++){
    		//debug info
            if(log.isDebugEnable()){
                log.debug("***merge cell beginrow:" + beginRow 
                        				+ " begincol:" + cols[i]
                        				+ " endRow:" + endRow
                        				+ " endCol:" + cols[i]
                        				);
            }
            
            param.sheet.mergeCells(cols[i], 
            		beginRow,
                    cols[i],
                    endRow);
    	}
    }
    
    protected ITempletContainer headTemplet = null; //头部模板容器
    protected ITempletContainer detailTemplet = null;//明细信息模板容器
    protected ITempletContainer bottomTemplet = null;//尾部模板容器信息
    protected ITempletContainer curTemplet = null;
    
    /**
     * 属性类：一个属性类保存了某个/某类模板元素的属性定义信息。
     * 继承类可以继承该类来定制自己的属性处理类 
     * @author juny
     */
    protected class BandProperty extends Property{
    	public int[] getMergeColum(){
    		String mergeColumn = this.getPropertyValue(AnalyseTempletTool.FIELD_PROPERTY_MERGECOLUM);
    		if(!HelpTools.notEmpty(mergeColumn)){
    			return null;
    		}
    		
    		String[] mergeColumnes = mergeColumn.split(AnalyseTempletTool.FIELD_PROPERTY_MERGECOLUM_SPLIT);
    		
    		int[] retList = null;
    		
    		if(null != mergeColumnes && null != detailTemplet){
    			if(mergeColumnes.length > 0){
        			retList = new int[mergeColumnes.length];
        		}
    			
    			BaseElement element = null;
    			for(int i=0; i<mergeColumnes.length; i++){
    				retList[i] = -1;
    				element = detailTemplet.getElement(mergeColumnes[i].trim());
    				if(null != element){
    					retList[i] = element.getTempletCellRef().getColumn();
    				}else{
    					try{
    						retList[i] = Integer.parseInt(mergeColumnes[i].trim());
    					}catch(Exception e){
    						log.error("Invalid merge property: [" + 
    								AnalyseTempletTool.FIELD_PROPERTY_MERGECOLUM 
    								+ "=" + mergeColumn
    								+ "]"
    								, e);
    					}
    				}
    			}
    		}
    		return retList;
    	}
    }
}